# 背景
交换机胖模式,因机器内存大小限制,不能随意引用外部插件。为了解决表格内容过长时的显示问题,于是自己实现手动拖动改变列宽功能,提升用户体验。
# 实现逻辑
首先在原有表格组件中增加配置选项,用来开启表格的列拖动功能,默认false。
表格配置项中的每列的宽度不能带单位,带单位会导致无法拖动(依据旧组件架构,只能出此下策)。通过改变表头的宽度,使tBody部分自动跟随。
在获取接口数据后,直接生成固定在顶部的表头,这个表头原本是在第一次滚动时生成的,这个css结构决定了后面的一系列妥协。
生成表头后为其绑定鼠标事件。
鼠标下落事件:
记录拖动元素的位置,宽度信息。特别提醒,位置需要用clientX获取,用x获取的话在IE下可能会不准(因为event.x如果是在relative定位的盒子中,是已该盒子进行计算的,而不是屏幕)。
鼠标移动事件:
保证列宽不为负的情况下,记录拖动后的宽度,并赋给当前元素。为了兼容ie9,需要同时赋值最小宽度。
因表头为了固定在顶部,旧的架构使用了另外一个table,给我们的改动宽度带来了很大的困难。这里在拖动后获取实际内容表格每列的宽度,再赋值给表头,来实现每列的宽度自动适应。
鼠标上事件:
清除数据,延迟100ms后再执行一次调整表头位置,防止快速拖动时导致的错位。
# 源码
/**
* 设置列宽可拖动
* @param $tab
* @private
*/
_setColConfig: function($tab) {
var me = this;
if (this.options.changeColWidth) {
var mainTable = this.$el[0].children[0]
var table = $tab || mainTable
var tTD; //用来存储当前更改宽度的Table Cell,避免快速移动鼠标的问题
for (j = 0; j < table.rows[0].cells.length; j++) {
table.rows[0].cells[j].onmousedown = function () {
//记录单元格
tTD = this;
if (event.offsetX > tTD.offsetWidth - 10) {
tTD.mouseDown = true;
tTD.oldX = event.clientX;
tTD.oldWidth = tTD.offsetWidth;
}
};
table.rows[0].cells[j].onmousemove = function () {
//更改鼠标样式
if (event.offsetX > this.offsetWidth - 10)
this.style.cursor = 'col-resize';
else
this.style.cursor = 'default';
//取出暂存的Table Cell
if (tTD == undefined) tTD = this;
//调整宽度
if (tTD.mouseDown != null && tTD.mouseDown == true) {
tTD.style.cursor = 'default';
if (tTD.oldWidth + (event.clientX - tTD.oldX) > 0) {
var tTdWidth = tTD.oldWidth + (event.clientX - tTD.oldX) + '';
tTD.width = tTdWidth
}
//调整列宽
tTD.style.width = tTdWidth + 'px';
tTD.style.minWidth = tTdWidth + 'px';
tTD.style.cursor = 'col-resize';
//调整该列中的每个Cell
table = tTD;
while (table.tagName != 'TABLE') table = table.parentElement;
for (j = 0; j < table.rows.length; j++) {
// 改变固定表头的宽度
table.rows[j].cells[tTD.cellIndex].width = tTdWidth;
table.rows[j].cells[tTD.cellIndex].style.width = tTdWidth + 'px';
// 改变主内容表格的宽度
if ($tab) {
mainTable.rows[j].cells[tTD.cellIndex].width = tTdWidth;
mainTable.rows[j].cells[tTD.cellIndex].style.width = tTdWidth + 'px';
mainTable.rows[j].cells[tTD.cellIndex].style.minWidth = tTdWidth + 'px';
}
}
if ($tab) {
me._setFixTableHeadWidth(table, mainTable)
}
}
};
table.rows[0].cells[j].onmouseup = function () {
//结束宽度调整
if (tTD == undefined) tTD = this;
tTD.mouseDown = false;
tTD.style.cursor = 'default';
// 结束时再执行一次,防止错位
if ($tab) {
setTimeout(function() {
me._setFixTableHeadWidth(table, mainTable)
}, 100)
}
};
}
}
},
/**
* 根据主内容表格的宽度来设置固定的表头的宽度
* @param table
* @param mainTable
* @private
*/
_setFixTableHeadWidth: function (table, mainTable) {
for (var k = 0; k < mainTable.rows[0].cells.length; k++) {
var width = mainTable.rows[0].cells[k].offsetWidth + 'px'
table.rows[0].cells[k].style.width = width
table.rows[0].cells[k].style.minWidth = width
}
},